package guowei.guliuser.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import guowei.common.exception.BizCodeEnume;
import guowei.common.utils.R;
import guowei.guliuser.user.exception.PhoneNotOnlyOneException;
import guowei.guliuser.user.exception.UserNameNotOnlyOneException;
import guowei.guliuser.user.service.MemberLevelService;
import guowei.guliuser.user.vo.LoginVoUser;
import guowei.guliuser.user.vo.RegMemVo;
import guowei.guliuser.user.vo.WeiBoToken;
import guowei.guliuser.user.vo.WeiboUser;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import guowei.common.utils.PageUtils;
import guowei.common.utils.Query;

import guowei.guliuser.user.dao.MemberDao;
import guowei.guliuser.user.entity.MemberEntity;
import guowei.guliuser.user.service.MemberService;


@Service("memberService")
public class MemberServiceImpl extends ServiceImpl<MemberDao, MemberEntity> implements MemberService {

    @Autowired
    private MemberLevelService memberLevelService;

    @Autowired
    private MemberDao memberDao;
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<MemberEntity> page = this.page(
                new Query<MemberEntity>().getPage(params),
                new QueryWrapper<MemberEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 将远程接收的 RegMemVo 保存
     * @param regMemVo
     */
    @Override
    public void saveRegMem(RegMemVo regMemVo) {
        MemberEntity memberEntity = new MemberEntity();

//  得到默认等级
        Long defaultLevel = memberLevelService.getDefaultLevel();
        memberEntity.setLevelId(defaultLevel);

//        得到密码
        String password = regMemVo.getPassword();
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String encode = passwordEncoder.encode(password);
        memberEntity.setPassword(encode);

//        1.检查用户名是否唯一
        String userName = regMemVo.getUserName();
        Boolean name = this.checkUserName(userName);
        if (name == true){
            memberEntity.setUsername(userName);
        }

//        2.检查用户手机号是否唯一
        String phone = regMemVo.getPhone();
        Boolean phone1 = this.checkPhone(phone);
        if (phone1 == true){
            memberEntity.setMobile(phone);
        }
        this.save(memberEntity);

    }

    @Override
    public Boolean checkUserName(String userName) {
        List<MemberEntity> list = memberDao.selectList(new QueryWrapper<MemberEntity>().eq("username", userName));
        if (list.size() > 0){
            throw new UserNameNotOnlyOneException();
        }
        return true;
    }

    @Override
    public Boolean checkPhone(String phone) {
        List<MemberEntity> list = memberDao.selectList(new QueryWrapper<MemberEntity>().eq("mobile", phone));
        if (list.size() > 0){
            throw new PhoneNotOnlyOneException();
        }
        return true;
    }

    /**
     * 远程传来的用户名和密码 ，验证是否正确。
     * @param vo
     * @return
     */
    @Override
    public R loginVo(LoginVoUser vo) {
        MemberEntity memberEntity = memberDao.selectOne(new QueryWrapper<MemberEntity>().eq("username", vo.getEupname()).or().eq("mobile", vo.getEupname()));
        if (memberEntity == null){
            return R.error(BizCodeEnume.EUPNAME_PHONE_PASSWORD_EXCEPTION.getCode(),BizCodeEnume.EUPNAME_PHONE_PASSWORD_EXCEPTION.getMsg());
        }
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        boolean matches = passwordEncoder.matches(vo.getPassword(), memberEntity.getPassword());
        if (matches == false){
            return R.error(BizCodeEnume.EUPNAME_PHONE_PASSWORD_EXCEPTION.getCode(),BizCodeEnume.EUPNAME_PHONE_PASSWORD_EXCEPTION.getMsg());
        }
        return R.ok().put("data",memberEntity);
    }

    /**
     * 保存微博登陆的用户信息  若第一次登录，则注册用户信息
     * @param
     * @return
     */
    @Override
    public R saveWeiboUser(WeiBoToken weiBoToken) {
        MemberEntity memberEntity = null;

//        先验证是否已经注册
        memberEntity = this.getOne(new QueryWrapper<MemberEntity>().eq("uid", weiBoToken.getUid()));
        if (memberEntity == null){
            memberEntity = new MemberEntity();
            WeiboUser userInfo = getUserInfo(weiBoToken);
            String name = userInfo.getName();
            long uid = userInfo.getId();
            memberEntity.setUid(uid);
            memberEntity.setUsername(name);
            memberEntity.setAccessToken(weiBoToken.getAccessToken());
            this.save(memberEntity);
            return R.ok().put("data",memberEntity);
        }else {     //如果登陆了就更新token
            MemberEntity entity = new MemberEntity();
            entity.setId(memberEntity.getId());
            entity.setUid(memberEntity.getUid());
            entity.setUsername(memberEntity.getUsername());
            entity.setAccessToken(weiBoToken.getAccessToken());
            this.updateById(entity);
            return R.ok().put("data",entity);
        }
    }
    //    https://api.weibo.com/2/statuses/show.json  获取用户信息

    public WeiboUser getUserInfo(WeiBoToken weiBoToken) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url("https://api.weibo.com/2/users/show.json?access_token="+weiBoToken.getAccessToken()+"&uid="+weiBoToken.getUid())
                .build();
        try {
            Response response = client.newCall(request).execute();
            String string = response.body().string();
            WeiboUser user = JSON.parseObject(string, new TypeReference<WeiboUser>(){});
            return user;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}